package com.file.manage.infrastructure.exception;


import cn.dev33.satoken.exception.NotLoginException;
import cn.dev33.satoken.exception.NotPermissionException;
import cn.dev33.satoken.exception.NotRoleException;
import cn.dev33.satoken.exception.SaTokenException;
import cn.dev33.satoken.util.SaResult;
import cn.hutool.json.JSONUtil;
import com.file.manage.domain.enums.UserRole;
import com.file.manage.infrastructure.base.CommonResult;
import com.file.manage.infrastructure.base.ResultCode;
import jakarta.validation.ValidationException;
import lombok.extern.slf4j.Slf4j;
import org.springframework.context.annotation.Configuration;
import org.springframework.stereotype.Component;
import org.springframework.validation.ObjectError;
import org.springframework.web.bind.MethodArgumentNotValidException;
import org.springframework.web.bind.annotation.ControllerAdvice;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.bind.annotation.RestControllerAdvice;
import org.springframework.web.method.annotation.MethodArgumentTypeMismatchException;

import java.net.SocketException;
import java.util.List;

/**
 * 统一异常处理
 *
 * @author: hsy
 * @since:
 */
@RestControllerAdvice
@Component
@Slf4j
public class GlobalExceptionHandler {


    public static final String DEFAULT_FAILURE_SERVER_ERROR = "程序内部错误";


    @ResponseBody
    @ExceptionHandler(ServiceException.class)
    public CommonResult<?> handleError(ServiceException e) {
        log.error(e.toString(), e);
        return CommonResult.failed(e.getCode(), e.getMessage());

    }

    @ResponseBody
    @ExceptionHandler({NotPermissionException.class, NotLoginException.class, NotRoleException.class})
    public CommonResult<?> handleSaTokenException(Exception e) {
        switch (e) {
            case NotLoginException notLoginException:
                log.error("请先登录", e);
                return CommonResult.failed(ResultCode.NOT_LOGIN);
            case NotRoleException notRoleException:
                if (UserRole.ADMIN.name().equals(notRoleException.getRole())) {
                    log.error("请勿越权使用！", e);
                    return CommonResult.failed("请勿越权使用！");
                }
                log.error("您无权限进行此操作！", e);
                return CommonResult.failed(ResultCode.NOT_PERMISSION);
            case NotPermissionException notPermissionException:
                log.error("您无权限进行此操作！", e);
                return CommonResult.failed(ResultCode.NOT_PERMISSION);
            default:
                return CommonResult.failed(ResultCode.FAILED);
        }
    }


    @ResponseBody
    @ExceptionHandler(MethodArgumentNotValidException.class)
    public CommonResult<?> handleError(MethodArgumentNotValidException e) {
        log.error(e.toString(), e);
        //这里只取其中一个报错信息
        List<ObjectError> allErrors = e.getBindingResult().getAllErrors();
        String errorMsg = null;
        if (null != allErrors.get(0) && (errorMsg = (allErrors.get(0)).getDefaultMessage()) != null) {
            return CommonResult.failed(errorMsg);

        }
        return CommonResult.failed(errorMsg);
    }

    @ResponseBody
    @ExceptionHandler({ValidationException.class, IllegalArgumentException.class})
    public CommonResult<?> handleError(Exception e) {
        log.error(e.toString(), e);
        return CommonResult.failed(e.getMessage());
    }

    @ResponseBody
    @ExceptionHandler({SocketException.class})
    public CommonResult<?> handleRuntimeError(Exception e) {
        log.error(e.toString(), e);
        return CommonResult.failed(DEFAULT_FAILURE_SERVER_ERROR);
    }

    @ResponseBody
    @ExceptionHandler(Throwable.class)
    public CommonResult<?> handleError(Throwable e) {
        log.error(e.toString(), e);
        return CommonResult.failed(DEFAULT_FAILURE_SERVER_ERROR);
    }

    @ResponseBody
    @ExceptionHandler(MethodArgumentTypeMismatchException.class)
    public CommonResult<?> handleMethodArgumentError(Throwable e) {
        log.error(e.toString(), e);
        return CommonResult.failed(ResultCode.ACTION_RESULT_STATUS_FAILURE_ILLEGAL_PARAMETERS);
    }


}
